<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2019/3/20
 * Time: 17:53
 */

namespace Game\Library;


use Game\Traits\Singleton;
use Game\Config\Config;

class Socket
{
    use Singleton;

    private $socket;
    private static $_socketObject;

    public function __construct($socket_name,$is_init=0)
    {
        if(empty(self::$_socketObject[$socket_name]) || $is_init == 1) {
            if($socket_name == "Timer") {
                $host = Config::Timer_Address;
                $port = Config::Timer_Port;
            } else if($socket_name == "Processor") {
                $host = Config::Processor_Address;
                $port = Config::Processor_Port;
            } else if($socket_name == "GameServer") {
                $host = Config::GameServer_Address;
                $port = Config::GameServer_Port;
            }

            //实例化游戏对象
            self::$_socketObject[$socket_name] = self::initSocket($host,$port);
        }
        return self::$_socketObject[$socket_name];
    }

    private static function initSocket($host = G_CONST::EMPTY_STRING,$port = G_CONST::EMPTY_STRING) {
        $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
        if ($socket === false) {
            self::writeSocketLog('error', "function(initSocket):socket_create() failed:".socket_strerror(socket_last_error())." in file".__FILE__." on Line ".__LINE__);
            return false;
        } else {
            $result = socket_connect($socket, $host, $port);
            if($result === false)  {
                self::writeSocketLog('error', "function(initSocket):socket_connect() failed.\nReason: () " . socket_strerror(socket_last_error($socket)) ." in file".__FILE__." on Line ".__LINE__);
                unset($socket);
                return false;
            }else {
                self::writeSocketLog('error', "function(initSocket):socket connect: prot:".$port." in file".__FILE__." on Line ".__LINE__);
                return $socket;
            }
        }
    }

    /**
     * send message
     * @param $socket_name
     * @param $message
     * @return bool
     */
    public function sendMessageToSocket($socket_name,$message) {
        //var_dump($message);
        $message .= "\n";
        $socketObject = self::getInstance($socket_name);
        $result = socket_write($socketObject, $message, strlen($message));
        if($result == false){
            $this->logMessage('error', "function(sendMessageToSocket):socket_write 1st failed :".$socket_name." in file".__FILE__." on Line ".__LINE__);
            $socketObject = self::getInstance($socket_name,$is_init=1);
            $result = socket_write($socketObject, $message, strlen($message));
            if($result == false){
                $this->logMessage('error', "function(sendMessageToSocket):socket_write 2nd failed :".$socket_name." in file".__FILE__." on Line ".__LINE__);
                return false;
            }
        }
        return true;
    }


    /**
     * close socket
     * @param $socket_name
     * @return bool
     */
    public function closeSocket($socket_name){
        if(isset(self::$_socketObject[$socket_name])){
            socket_close(self::$_socketObject[$socket_name]);
        }
        return true;
    }

    private function logMessage($level, $content){
        Logger::getInstance()->log($content, $level);
    }

    /**
     * 写日志
     * @param $level
     * @param $content
     */
    private static function writeSocketLog($level,$content){
        Logger::getInstance()->socket($content, $level);
    }
}